package com.electromagnetic.industry.software.manage.service.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.electromagnetic.industry.software.common.enums.DataOwnEnum;
import com.electromagnetic.industry.software.common.enums.EleDataTypeEnum;
import com.electromagnetic.industry.software.common.enums.FileBackupSource;
import com.electromagnetic.industry.software.common.pojo.RespPageVO;
import com.electromagnetic.industry.software.common.resp.ElectromagneticResult;
import com.electromagnetic.industry.software.common.util.EleCommonUtil;
import com.electromagnetic.industry.software.common.util.ElectromagneticResultUtil;
import com.electromagnetic.industry.software.common.util.UserThreadLocal;
import com.electromagnetic.industry.software.manage.mapper.EdFileInfoMapper;
import com.electromagnetic.industry.software.manage.mapper.FileBackupLogMapper;
import com.electromagnetic.industry.software.manage.pojo.models.EdFileInfo;
import com.electromagnetic.industry.software.manage.pojo.models.FileBackupLog;
import com.electromagnetic.industry.software.manage.pojo.resp.FileBackLogVO;
import com.electromagnetic.industry.software.manage.service.FileBackLogService;
import com.electromagnetic.industry.software.manage.tasks.BackupHandler;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FileBackLogServiceImpl extends ServiceImpl<FileBackupLogMapper, FileBackupLog> implements FileBackLogService {

    @Resource
    private EdFileInfoMapper edFileInfoMapper;
    @Resource
    private BackupHandler backupHandler;
    @Resource
    private CommonService commonService;

    @Override
    public ElectromagneticResult<?> query(Integer pageNumber, Integer pageSize) {

        Page<FileBackupLog> fileBackupLogPage = this.baseMapper.selectPage(new Page<>(pageNumber, pageSize), Wrappers.<FileBackupLog>lambdaQuery()
                .orderByDesc(FileBackupLog::getFileId)
                .eq(FileBackupLog::getSource, FileBackupSource.SYS_BACKUP.code));
        List<FileBackupLog> records = fileBackupLogPage.getRecords();

        if (CollUtil.isEmpty(records)) {
            UserThreadLocal.setSuccessInfo("", "", "查询备份日志成功");
            return ElectromagneticResultUtil.success(new RespPageVO<>(0L, records));
        }

        List<String> fileIds = records.stream().map(FileBackupLog::getFileId).toList();
        List<EdFileInfo> edFileInfos = edFileInfoMapper.selectList(Wrappers.<EdFileInfo>lambdaQuery()
                .select(EdFileInfo.class, file -> !StrUtil.equals(file.getColumn(), "file_content"))
                .in(EdFileInfo::getId, fileIds));
        Map<String, EdFileInfo> map = edFileInfos.stream().collect(Collectors.toMap(EdFileInfo::getId, e -> e));
        Map<String, String> paths = commonService.getFilesPath(edFileInfos.stream().map(EdFileInfo::getFilePath).collect(Collectors.toList()));
        long total = fileBackupLogPage.getTotal();
        List<FileBackLogVO> list = new ArrayList<>();
        for (FileBackupLog fileBackupLog : records) {
            FileBackLogVO fileBackLogVO = BeanUtil.copyProperties(fileBackupLog, FileBackLogVO.class);
            fileBackLogVO.setBackStartTime(DateUtil.date(fileBackupLog.getStartTime()));
            fileBackLogVO.setBackEndTime(DateUtil.date(fileBackupLog.getEndTime()));
            fileBackLogVO.setDataOwn(map.get(fileBackupLog.getFileId()).getDataOwn());
            fileBackLogVO.setDataOwner(DataOwnEnum.getEnumByCode(map.get(fileBackupLog.getFileId()).getDataOwn()).type);
            fileBackLogVO.setFilePath(paths.get(map.get(fileBackupLog.getFileId()).getFilePath()));
            list.add(fileBackLogVO);
        }

        UserThreadLocal.setSuccessInfo("", "", "查询备份日志成功");
        return ElectromagneticResultUtil.success(new RespPageVO<>(total, list));
    }

    @Override
    public Long restore() {
        List<EdFileInfo> edFileInfos = edFileInfoMapper.selectList(Wrappers.lambdaQuery(EdFileInfo.class)
                .select(EdFileInfo.class, file -> !StrUtil.equals(file.getColumn(), "file_content"))
                .eq(EdFileInfo::getPermanentDeleted, false)
                .eq(EdFileInfo::getDataType, EleDataTypeEnum.FILE.code));
        for (EdFileInfo edFileInfo : edFileInfos) {

            String destPath = EleCommonUtil.simpleTrueFalse(DataOwnEnum.isUserCode(edFileInfo.getDataOwn()),
                    commonService.getPrjRootPath1(edFileInfo.getDataOwn()) + File.separator + edFileInfo.getCreatedBy() + File.separator + edFileInfo.getId(),
                    commonService.getPrjRootPath1(edFileInfo.getDataOwn()) + File.separator + edFileInfo.getId());
            destPath = destPath.replace("//", "/");
            log.info("back up file path is {}", destPath);
            if (!FileUtil.exist(destPath)) {
                byte[] bytes = backupHandler.downloadFile(edFileInfo.getId());
                FileUtil.writeBytes(bytes, destPath);
                String dbPath = commonService.getDbPath(edFileInfo.getFilePath());
                UserThreadLocal.setSuccessInfo(edFileInfo.getParentId(), edFileInfo.getId(), "{} 恢复成功，路径为 {}", edFileInfo.getFileName() + "." + edFileInfo.getFileType(), dbPath);
            }
        }
        List<FileBackupLog> fileBackupLogs = this.baseMapper.selectList(Wrappers.<FileBackupLog>lambdaQuery().orderByDesc(FileBackupLog::getEndTime).last(" limit 1"));
        if (CollUtil.isEmpty(fileBackupLogs)) {
            return 0L;
        }
        Long endTime = fileBackupLogs.get(0).getEndTime();
        UserThreadLocal.setSuccessInfo("", "", "数据库恢复成功，最新时间戳为 {}", endTime);
        return endTime;
    }
}
